/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cn.icanci.learn.v1.aop4;

import cn.icanci.learn.v1.aop3.TargetMethod;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;

/**
 * @author icanci
 * @date Created in 2021/06/27 17:00
 * @version  1.0
 */
@SuppressWarnings("all")
public class JDKDynamicProxy4 implements InvocationHandler {
    /**
     * 被代理对象
     */
    private Object                    target;

    /**
     * 方法拦截器列表
     */
    private List<MyMethodInterceptor> interceptors = new ArrayList<>();

    public void setInterceptor(MyMethodInterceptor myMethodInterceptor) {
        this.interceptors.add(myMethodInterceptor);
    }

    public void setInterceptors(List<MyMethodInterceptor> myMethodInterceptors) {
        this.interceptors.addAll(myMethodInterceptors);
    }

    public JDKDynamicProxy4(Object target) {
        this.target = target;
    }

    /**
     * 代理
     * @param proxy 代理对象，内部持有 target 对象
     * @param method 被代理对象的方法
     * @param args 被代理对象的方法的参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        final TargetMethod targetMethod = new TargetMethod();
        targetMethod.setTarget(target);
        targetMethod.setMethod(method);
        targetMethod.setArgs(args);
        final MyMethodInvocationImpl myMethodInvocation = new MyMethodInvocationImpl(targetMethod, interceptors);
        return myMethodInvocation.proceed();
    }

    /**
     * 返回代理之后的对象
     */
    public Object getProxy() {
        // 参数1：类加载器
        // 参数2：代理类需要实现的接口
        // 参数3：代理类的实现
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }
}
